/*
 * @Author: soso
 * @Date: 2022-01-26 10:56:33
 * @LastEditTime: 2022-03-03 17:51:06
 * @LastEditors: Please set LastEditors
 * @Description: sonet传输包
 * @FilePath: /go-mesh-sync/go-utils/utils/sonet/command.go
 */
package sonet

import (
	"errors"
	"io"
	"net"
	"os"
)

const (
	timeout   = 3
	retryTime = 3
	bufSize   = 16384 // 8192 8k, 16384 16k, 32768 32k
)

/**
 * @description: 读取命令数据
 * @param {net.Conn} conn
 * @return {*}
 */
func Read(conn net.Conn) (uint32, []byte, error) {
	msg, err := ReceivePack(conn)
	if err != nil {
		return 0, nil, err
	}
	return msg.GetMsgId(), msg.GetData(), nil
}

/**
 * @description: 写入自拼写命令
 * @param {net.Conn} conn
 * @param {[]byte} command
 * @return {*}
 */
func Write(conn net.Conn, command []byte) error {
	err := SendPack(conn, 0, command)
	return err
}

//发送文件
func SendFileData(conn net.Conn, filePath string, offset, expectSize int64, cbFunc func(sentN int)) (int, error) {
	fd, err := os.OpenFile(filePath, os.O_RDONLY, os.ModePerm)
	if err != nil {
		return 0, err
	}
	defer fd.Close()

	_, err = fd.Seek(offset, 0)
	if err != nil {
		return 0, err
	}

	buf := make([]byte, bufSize)
	var packNum uint32 = 0
	sent := 0
	for {
		n, err := fd.Read(buf)
		if err == io.EOF {
			break
		}
		if err != nil {
			return 0, err
		}
		// check if out of range
		if expectSize > 0 && int64(sent+n) > expectSize {
			n -= (sent + n) - int(expectSize)
		}
		err = SendPack(conn, packNum, buf[:n])
		if err != nil {
			return sent, err
		}
		sent += n
		packNum += 1
		if cbFunc != nil {
			cbFunc(n)
		}
		if expectSize > 0 && sent >= int(expectSize) {
			break
		}
	}
	return sent, nil
}

/**
 * @description: 接收长数据
 * @param {net.Conn} conn
 * @param {func} callbackFunc
 * @return {error}
 */
func ReceiveLongData(conn net.Conn, callbackFunc func([]byte) bool) error {
	var packNumber uint32 = 0
	for {
		_n, buf, err := Read(conn)
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return err
		}
		if _n != packNumber {
			return errors.New("pack is wrong")
		}
		if !callbackFunc(buf) {
			return nil
		}
		packNumber += 1
	}
}
